package com.openvid.webrtc.openvid.decoder;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class AudioDecoderThread extends Thread {

    private static final String TAG = "VideoThread";
    private static final long TIMEOUT_US = 10_000;

    private MediaExtractor mExtractor;
    private MediaCodec mDecoder;
    private boolean isEndOfStream = false;


    private File mSourceFile;
    private IAudioData mDataCallback;

    private int mSampleRate;
    private int mChannelCount;
    private int mFrameSleep;

    public AudioDecoderThread(File sourceFile, IAudioData callback) {
        mSourceFile = sourceFile;
        mDataCallback = callback;
    }

    @Override
    public void run() {

        if (!mSourceFile.exists()) {
            return;
        }

        initMediaCodec();
        if (mDecoder == null) {
            return;
        }
        //同步处理
        decodecAacToPCMSync();


        if (mDataCallback != null) {
            mDataCallback.onAudioEnd(mSourceFile);
        }
    }


    private VideoSpeedController mSpeedControl=new VideoSpeedController();

    private void initMediaCodec() {


        mExtractor = new MediaExtractor();
        try {
            mExtractor.setDataSource(mSourceFile.getPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        int trackCount = mExtractor.getTrackCount();
        for (int i = 0; i < trackCount; i++) {
            MediaFormat trackFormat = mExtractor.getTrackFormat(i);
            String mime = trackFormat.getString(MediaFormat.KEY_MIME);
            if (TextUtils.isEmpty(mime)) {
                continue;
            }
            if (mime.startsWith("audio/")) {

                mSampleRate = trackFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                mChannelCount = trackFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                mFrameSleep=1024*1000/mSampleRate;
                mExtractor.selectTrack(i);
                //生成MediaCodec，此时处于Uninitialized状态
                try {
                    mDecoder = MediaCodec.createDecoderByType(mime);
                    //configure 处于Configured状态
                    mDecoder.configure(trackFormat, null, null, 0);
                    //处于Excuting状态 Flushed子状态
                    mDecoder.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }

        }
    }

    private void decodecAacToPCMSync() {
//        FileOutputStream fileOutputStream = null;
//        try {
//            File file=new File("/sdcard/debugdecode.pcm");
//            if (!file.exists()){
//                file.createNewFile();
//            }
//            fileOutputStream = new FileOutputStream(file);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        while (!isInterrupted()) {
            if (!isEndOfStream) {
                int index = mDecoder.dequeueInputBuffer(TIMEOUT_US);
                if (index >= 0) {
                    ByteBuffer inputBuffer;
                    inputBuffer = mDecoder.getInputBuffer(index);
                    if (inputBuffer != null) {
                        inputBuffer.clear();
                    }
                    int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
                    if (sampleSize < 0) {
                        isEndOfStream = true;
                        mDecoder.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    } else {
                        mDecoder.queueInputBuffer(index, 0, sampleSize, mExtractor.getSampleTime(), 0);
                        //读取下一帧
                        mExtractor.advance();
                    }
                }
            }
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            int index = mDecoder.dequeueOutputBuffer(bufferInfo, TIMEOUT_US);
            if (index < 0) {
                continue;
            }
            ByteBuffer outputBuffer = mDecoder.getOutputBuffer(index);

            byte[] pcmBytes = new byte[bufferInfo.size];
            outputBuffer.get(pcmBytes);

            try {
                Log.i("223223","mFrameSleep:"+mFrameSleep);
                Thread.sleep(mFrameSleep);
            } catch (InterruptedException e) {
                break;
            }

            if (mDataCallback!=null){
                mDataCallback.onAudioFrame(pcmBytes,0);
            }

//            try {
//                fileOutputStream.write(pcmBytes);
//                fileOutputStream.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
            mDecoder.releaseOutputBuffer(index, false);
            if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                break;
            }
        }
        release();
    }

    private void release() {
        mExtractor.release();
        mDecoder.stop();
        mDecoder.release();
//        try {
//            fileOutputStream.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    public void seekTo(long time) {
        if (mExtractor != null) {
            mExtractor.seekTo(time, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
        }
    }

    public interface IAudioData {

        void onAudioFrame(byte[] data, long ts);

        void onAudioEnd(File sourceFile);
    }

}
